"""
Copyright (c) 2022 Huawei Technologies Co.,Ltd.

openGauss is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:

          http://license.coscl.org.cn/MulanPSL2

THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
"""
"""
Case Type   : 行存表压缩
Case Name   : 检查行存压缩表不同数据量下压缩率
Create At   : 2022/05/31
Owner       : @wan005
Description :
    1.创建行存压缩表与非行存压缩表
    2.创建列存表
    3.向列存表中插入数据
    4.对该列存表进行逻辑解码
    5.删除新建逻辑复制槽
Expect      :
    1.成功
    2.创建列存表成功
    3.向列存表中插入数据成功
    4.对该列存表进行逻辑解码失败，插入的数据并未解析出来
    5.删除新建逻辑复制槽成功
History     :
"""

import os
import unittest

from yat.test import Node
from yat.test import macro

from testcase.utils.CommonSH import CommonSH
from testcase.utils.Constant import Constant
from testcase.utils.Logger import Logger
from testcase.xUtils.ComRowCompress import ComRowCompress


class RowCompress(unittest.TestCase):
    def setUp(self):
        self.log = Logger()
        self.log.info(f'-----{os.path.basename(__file__)} start-----')
        self.pri_sh = CommonSH('PrimaryDbUser')
        self.pri_node = Node('PrimaryDbUser')
        self.constant = Constant()
        self.compress = ComRowCompress()
        self.t_name_compress = 't_compress_0009'
        self.t_name_nocompress = 't_nocompress_0009'

    def test_rowcompress(self):
        text = '-----test1:检查空表状态下压缩率-----'
        self.log.info(text)
        text = '-----step1:创建行存压缩表与非行存压缩表 expect:成功-----'
        self.log.info(text)
        result = self.compress.create_compare_table(
                     self.t_name_compress, self.t_name_nocompress)
        self.log.info(result)
        self.assertTrue(result.count(self.constant.CREATE_TABLE_SUCCESS) == 2,
                        '执行失败:' + text)

        text = '-----step2:查看行存压缩表是否有_compress文件 expect:有_compress文件-----'
        self.log.info(text)
        self.dusize = self.compress.check_compress_file(self.t_name_compress)
        self.assertNotEqual(-1, self.dusize, '执行失败:' + text)

        text = '-----step3:获取两个表的大小 expect:非行存压缩为0，行存压缩为0，与step2大小一致-----'
        self.log.info(text)
        query_sql = f"select pg_relation_size('{self.t_name_compress}');" \
                    f"select pg_relation_size('{self.t_name_nocompress}');"
        result = self.pri_sh.execut_db_sql(query_sql)
        self.log.info(result)
        self.assertTrue(result.count('pg_relation_size') == 2,
                        '执行失败:' + text)
        self.compress_size = result.splitlines()[2].strip()
        self.nocompress_size = result.splitlines()[-2].strip()
        self.assertEqual(self.compress_size, '0', '执行失败:' + text)
        self.assertEqual(int(self.compress_size), self.dusize, '执行失败:' + text)
        self.assertEqual(self.nocompress_size, '0')

        text = '-----step4:比较压缩表与非压缩表内容是否一致 expect:内容一致-----'
        self.log.info(text)
        result = self.compress.check_data_content(
                     self.t_name_compress, self.t_name_nocompress)
        self.log.info(result)
        self.assertTrue(result.count('checksum') == 2,
                        '执行失败:' + text)
        self.assertEqual(result.splitlines()[2].strip(),
                         result.splitlines()[-2].strip())

        text = '-----test2:检查500M数据量下压缩情况-----'
        self.log.info(text)
        text = '-----step5:往行存压缩表与非行存压缩表中插入500M数据 expect:成功-----'
        self.log.info(text)
        insert_sql = f"insert into {self.t_name_compress} " \
                     f"values(generate_series(1, 1500000));" \
                     f"insert into {self.t_name_nocompress} " \
                     f"values(generate_series(1, 1500000));" \
                     f"checkpoint;"
        result = self.pri_sh.execut_db_sql(insert_sql)
        self.log.info(result)
        self.assertTrue(result.count(self.constant.INSERT_SUCCESS_MSG) == 2,
                        '执行失败:' + text)
        self.assertIn(self.constant.CHECKPOINT_SUCCESS_MSG, result, text)

        text = '-----step6:查看行存压缩表是否有_compress文件 expect:有_compress文件-----'
        self.log.info(text)
        self.dusize = self.compress.check_compress_file(self.t_name_compress)
        self.assertNotEqual(-1, self.dusize, '执行失败:' + text)

        text = '-----step7:获取两个表的大小 expect:大小满足预期，压缩表与step6大小一致-----'
        self.log.info(text)
        query_sql = f"select pg_relation_size('{self.t_name_compress}');" \
                    f"select pg_relation_size('{self.t_name_nocompress}');"
        result = self.pri_sh.execut_db_sql(query_sql)
        self.log.info(result)
        self.assertTrue(result.count('pg_relation_size') == 2,
                        '执行失败:' + text)
        self.compress_size = result.splitlines()[2].strip()
        self.nocompress_size = result.splitlines()[-2].strip()
        self.assertEqual(int(self.compress_size), self.dusize, '执行失败:' + text)
        compress_rate = float(self.nocompress_size)/float(self.compress_size)
        self.assertAlmostEqual(compress_rate, 2, delta=0.1)

        text = '-----step8:比较压缩表与非压缩表内容是否一致 expect:内容一致-----'
        self.log.info(text)
        result = self.compress.check_data_content(
                     self.t_name_compress, self.t_name_nocompress)
        self.log.info(result)
        self.assertTrue(result.count('checksum') == 2,
                        '执行失败:' + text)
        self.assertEqual(result.splitlines()[2].strip(),
                         result.splitlines()[-2].strip())

        text = '-----test3:检查2G数据量下压缩情况-----'
        self.log.info(text)
        text = '-----step9:往行存压缩表与非行存压缩表中插入2G数据 expect:成功-----'
        self.log.info(text)
        insert_sql = f"insert into {self.t_name_compress} " \
                     f"values(generate_series(1500001, 5800000));" \
                     f"insert into {self.t_name_nocompress} " \
                     f"values(generate_series(1500001, 5800000));" \
                     f"checkpoint;"
        result = self.pri_sh.execut_db_sql(insert_sql)
        self.log.info(result)
        self.assertTrue(result.count(self.constant.INSERT_SUCCESS_MSG) == 2,
                        '执行失败:' + text)
        self.assertIn(self.constant.CHECKPOINT_SUCCESS_MSG, result, text)

        text = '-----step10:查看行存压缩表是否有_compress文件 expect:有_compress文件-----'
        self.log.info(text)
        self.dusize = self.compress.check_compress_file(self.t_name_compress)
        self.assertNotEqual(-1, self.dusize, '执行失败:' + text)

        text = '-----step11:获取两个表的大小 expect:大小满足预期-----'
        self.log.info(text)
        query_sql = f"select pg_relation_size('{self.t_name_compress}');" \
                    f"select pg_relation_size('{self.t_name_nocompress}');"
        result = self.pri_sh.execut_db_sql(query_sql)
        self.log.info(result)
        self.assertTrue(result.count('pg_relation_size') == 2,
                        '执行失败:' + text)
        self.compress_size = result.splitlines()[2].strip()
        self.nocompress_size = result.splitlines()[-2].strip()
        self.assertEqual(int(self.compress_size), self.dusize, '执行失败:' + text)
        compress_rate = float(self.nocompress_size)/float(self.compress_size)
        self.assertAlmostEqual(compress_rate, 2, delta=0.1)

        text = '-----step12:比较压缩表与非压缩表内容是否一致 expect:内容一致-----'
        self.log.info(text)
        result = self.compress.check_data_content(
                     self.t_name_compress, self.t_name_nocompress)
        self.log.info(result)
        self.assertTrue(result.count('checksum') == 2,
                        '执行失败:' + text)
        self.assertEqual(result.splitlines()[2].strip(),
                         result.splitlines()[-2].strip())

    def tearDown(self):
        self.log.info('----------------this is tearDown-----------------------')
        self.log.info(
            '------------------------删除表-----------------')
        del_sql = f"drop table {self.t_name_compress};" \
                  f"drop table {self.t_name_nocompress};"
        msg = self.pri_sh.execut_db_sql(del_sql)
        self.log.info('-----{os.path.basename(__file__)} end-----')
